package com.filex.ads.network;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.filex.ads.common.AdFormat;
import com.filex.ads.common.Preconditions;
import com.filex.ads.common.logging.Logger;
import com.filex.ads.volley.DefaultRetryPolicy;
import com.filex.ads.volley.NetworkResponse;
import com.filex.ads.volley.Response;
import com.filex.ads.volley.toolbox.HttpHeaderParser;

import org.json.JSONArray;
import org.json.JSONObject;


public class AdRequest extends FilexRequest<AdResponse> {

    @NonNull
    public final Listener mListener;
    @NonNull
    final AdFormat mAdFormat;
    @Nullable
    final String mPlacementId;

    private int hashCode = 0;

    public interface Listener extends Response.ErrorListener {
        void onSuccessResponse(AdResponse response);
    }

    AdRequest(@NonNull final String url,
              @NonNull final AdFormat adFormat,
              @Nullable final String adToken,
              @NonNull final Context context,
              @NonNull final Listener listener) {
        super(context, url, listener);
        Preconditions.checkNotNull(url);
        Preconditions.checkNotNull(adFormat);
        Preconditions.checkNotNull(context);
        Preconditions.checkNotNull(listener);

        mPlacementId = adToken;
        mListener = listener;
        mAdFormat = adFormat;

        DefaultRetryPolicy retryPolicy = new DefaultRetryPolicy(
                DefaultRetryPolicy.DEFAULT_TIMEOUT_MS,
                DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
        setRetryPolicy(retryPolicy);
        setShouldCache(false);
    }


    @Nullable
    @Override
    protected Response<AdResponse> parseNetworkResponse(NetworkResponse networkResponse) {
        AdResponse adResponse;
        try {
            String responseBody = parseStringBody(networkResponse);
            JSONObject jsonResponse = new JSONObject(responseBody);
            JSONArray adJSONArray = jsonResponse.getJSONArray("ads");
            if (adJSONArray == null || adJSONArray.length() == 0) {
                return Response.error(new FilexNetworkError(FilexNetworkError.Reason.NO_FILL));
            }
            adResponse = new AdResponse(mPlacementId, mAdFormat, adJSONArray);
        } catch (Exception ex) {
            if (ex instanceof FilexNetworkError) {
                return Response.error((FilexNetworkError) ex);
            }
            // Volley network error
            Logger.e("parseNetworkResponse error msg:" + ex.getMessage());
            return Response.error(new FilexNetworkError(ex, FilexNetworkError.Reason.UNSPECIFIED));
        }

        return Response.success(adResponse, HttpHeaderParser.parseCacheHeaders(networkResponse));
    }

    @Override
    protected void deliverResponse(AdResponse adResponse) {
        if (!isCanceled()) {
            mListener.onSuccessResponse(adResponse);
        }
    }

    @Override
    public void cancel() {
        super.cancel();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this)
            return true;

        if (!(obj instanceof AdRequest)) {
            return false;
        }

        AdRequest other = (AdRequest) obj;
        int res = 0;
        if (mPlacementId != null) {
            res = other.mPlacementId == null ? 1 : mPlacementId.compareTo(other.mPlacementId);
        } else if (other.mPlacementId != null) {
            res = -1;
        }

        return res == 0
                && mAdFormat == other.mAdFormat
                && getUrl().compareTo(other.getUrl()) == 0;
    }

    @Override
    public int hashCode() {
        if (hashCode == 0) {
            int result = mPlacementId == null ? 29 : mPlacementId.hashCode();
            result = 31 * result + mAdFormat.hashCode();
            result = 31 * result + getOriginalUrl().hashCode();
            hashCode = result;
        }
        return hashCode;
    }

}
